<template>
	<view class="content">
		<u-toast ref="uToast"></u-toast>
		<view class="notic-box">
			蓝牙设备id：{{deviceId}}
		</view>
		<u--input placeholder="请输入发送值" border="surround" style="width: 100%;" v-model="value"></u--input>
		<u-button @click="writeBLECharacteristicValue" type="primary">发送指令</u-button>
		<view>解析值：</view>
		<view class="text">{{msg}}</view>
	</view>
</template>

<script>
	let ecServerIdOption1 = "0000FFF0-0000-1000-8000-00805F9B34FB"; // 服务id
	let ecWriteCharacteristicIdOption1 = "0000FFF2-0000-1000-8000-00805F9B34FB"; // 写特征值id
	let ecReadCharacteristicIdOption1 = "0000FFF1-0000-1000-8000-00805F9B34FB"; // 读特征值id

	// buff 转 str 
	function arrayBufferToString(buffer) {
		let x = new Uint8Array(buffer);
		// log(x)
		let strHex = ""
		let str = ""
		for (let i = 0; i < x.length; i++) {
			strHex = strHex + x[i].toString(16).padStart(2, "0")
			str = str + String.fromCharCode(x[i])
		}
		return strHex;
	}
	// str 转 buff
	function str2ab(str) {
		const buffer = new ArrayBuffer(str.length / 2);
		let x = new Uint8Array(buffer);
		for (let i = 0; i < x.length; i++) {
			x[i] = parseInt(str.substr(2 * i, 2), 16)
		}
		return buffer;
	}
	export default {
		data() {
			return {
				value: '',
				serviceId: '',
				characteristicId: '',
				services: [], // 服务id
				characteristics: [], // 特征值id
				deviceId: '',
				msg: '',
				title: 'Hello',
			}
		},
		computed: {
			character() {
				const o = this.characteristics.find(v => v.uuid == this.characteristicId);
				return o;
			}
		},
		onUnload() {
			this.closeBLEConnection();
			console.log('onUnload');
		},
		onLoad(option) {
			const vm = this;
			this.deviceId = option.deviceId || '';
			this.createBLEConnection(this.deviceId);
			// 监听特征值
			uni.onBLECharacteristicValueChange(function(characteristic) {
				vm.msg = arrayBufferToString(characteristic.value);
				console.log('buff解析出来的字符串:', vm.msg);
				console.log('characteristic value comed:', characteristic);
			});
		},
		methods: {
			// 读取特征值返回数据
			readBLECharacteristicValue() {
				const vm = this;
				uni.readBLECharacteristicValue({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId: vm.deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId: ecServerIdOption1,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId: ecReadCharacteristicIdOption1,
					success(res) {
						console.log('readBLECharacteristicValue:', res);
						// vm.msg = ab2str(res.value);
					},
					fail(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'error',
							message: res.errMsg
						});
					}
				});
			},
			radioChange(serviceId) {
				this.getBLEDeviceCharacteristics(this.deviceId, serviceId);
				console.log(serviceId, 'serviceId');
			},
			openBLEConnection() {
				this.createBLEConnection(this.deviceId);
			},
			// 链接蓝牙服务
			createBLEConnection(deviceId, cb) {
				const vm = this;
				uni.createBLEConnection({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId,
					success(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'success',
							message: `${deviceId}-蓝牙建立链接成功`
						});
						vm.getBLEDeviceServices(vm.deviceId);

						// 兼容app端，app端首次加载可能不会获取到对应的服务列表，需要多次刷新请求触发
						vm.severId = setInterval(() => {
							if (vm.services.length) {
								clearInterval(vm.severId);
							}
							vm.getBLEDeviceServices(vm.deviceId);
						}, 3000);

						console.log(res, '连接成功蓝牙');
					},
					fail(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'error',
							message: res.errMsg
						});
					}
				})
			},
			// 关闭蓝牙连接成功
			closeBLEConnection() {
				const deviceId = this.deviceId;
				const vm = this;
				uni.closeBLEConnection({
					deviceId,
					success(res) {
						console.log(res);
						vm.$refs.uToast.show({
							position: 'center',
							type: 'success',
							message: `关闭蓝牙链接成功`
						});
					}
				});
			},
			// 发送对应的指令
			writeBLECharacteristicValue(value = this.value) {

				if (this.value.length % 2 != 0) {
					this.$refs.uToast.show({
						position: 'center',
						type: 'error',
						message: `数据长度只能是双数`
					});
					return;
				}

				if (!new RegExp("^[0-9a-fA-F]*$").test(this.value)) {
					this.$refs.uToast.show({
						position: 'center',
						type: 'error',
						message: `数据格式错误，只能是0-9,a-f,A-F`
					});
					return;
				}

				const vm = this;
				const buffer = str2ab(this.value);

				console.log('发送的蓝牙特征值：', buffer);

				uni.writeBLECharacteristicValue({
					// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
					deviceId: vm.deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId: ecServerIdOption1,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId: ecWriteCharacteristicIdOption1,
					// 这里的value是ArrayBuffer类型
					value: buffer,
					success(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'success',
							message: res.errMsg
						});
						console.log('writeBLECharacteristicValue success', JSON.stringify(res));
						vm.res = res;
					},
					fail(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'error',
							message: res.errMsg
						});
					}
				});
			},
			// 获取服务对应的特征值
			getBLEDeviceCharacteristics(deviceId = this.deviceId, serviceId = ecServerIdOption1) {
				const vm = this;
				uni.getBLEDeviceCharacteristics({
					deviceId,
					serviceId,
					success(res) {
						console.log('device characteristics:', res.characteristics);
						vm.characteristics = res.characteristics;
						vm.characteristicId = res.characteristics[0].uuid || '';

						// 必须先获取服务，再获取特征值，然后再进行监听。这个步骤必须走完才可以完成监听，不然走不通。后面onBLECharacteristicValueChange
						uni.notifyBLECharacteristicValueChange({
							state: true, // 启用 notify 功能
							// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
							deviceId: vm.deviceId,
							// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
							serviceId: ecServerIdOption1,
							// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
							characteristicId: ecReadCharacteristicIdOption1, // 读服务特征值
							success(res) {
								console.log('notifyBLECharacteristicValueChange连接成功', res);
							}
						});
					}
				});
			},
			getBLEDeviceServices(deviceId) {
				const vm = this;
				uni.getBLEDeviceServices({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId,
					success(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'success',
							message: '获取蓝牙设备服务成功'
						});
						console.log('获取蓝牙设备服务成功', JSON.stringify(res));

						vm.services = res.services;
						vm.getBLEDeviceCharacteristics(vm.deviceId, ecServerIdOption1);
					},
					fail(res) {
						vm.$refs.uToast.show({
							position: 'center',
							type: 'error',
							message: res.errMsg
						});
					}
				});
			},
			// 上传图片
			upload() {
				uni.chooseImage({
					count: 1,
					success(res) {
						console.log(res);
						if (res.tempFilePaths.length > 0) {
							let filePath = res.tempFilePaths[0];
							//进行上传操作

							// promise方式
							uniCloud.uploadFile({
								filePath: filePath, //要上传的文件对象
								cloudPath: Date.now() + '.jpg', //保存在云端的文件名，这里以时间戳命名
								success(res) {
									console.log(res, 'res---');
								}
							});
						}
					}
				});
			}
		}
	}
</script>
<style lang="scss" scoped>
	.notic-box {
		width: 100%;
	}

	.content {
		padding: 5px;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;

		::v-deep.u-input {
			width: 95%;
		}

		::v-deep.u-button {
			margin: 10rpx 0;
		}

		.text {
			width: 98%;
			height: 200rpx;
			overflow: auto;
			white-space: pre-wrap;
			word-break: break-all;
		}
	}
</style>